﻿using System.Net;
using System.Xml;
using System;
using System.IO;
using System.Net.Sockets;
using System.Linq;
using System.Collections.Generic;
using Protocolo.Utilidades;
using Protocolo.AnchoDeBanda;

namespace Servidor
{
    public class DatosServidor
    {
        public int PuertoUDPClientes { get; set; }
        public int PuertoTCPClientes { get; set; }
        public string FileRepository { get; set; }
        public string IPServidor { get; set; }
        public int PuertoUDPSincronizarServidores { get; set; }
        public int PuertoTCPSincronizarServidores { get; set; }
        public int IntervaloSincronizacionServidores { get; set; }
        public int CantidadMaximaConexionesSincronizacion { get; set; }
        public AnchoDeBandaServidor AnchoDeBandaServidor { get; set; }
        public Dictionary<string, string> Archivos_MD5 { get; set; }
        public Dictionary<string, SyncAnchoDeBanda> Servidores_AnchoDeBanda { get; set; }       

        public int MaxConexionesClientes
        {
            get
            {
                return (int)(this.AnchoDeBandaServidor.AnchoDeBandaTotal / this.AnchoDeBandaServidor.AnchoDeBandaXCliente);
            }
        }

        private static DatosServidor _instancia = null;

        public static DatosServidor Instancia
        {
            get
            {
                if (_instancia == null)
                {
                    _instancia = new DatosServidor();
                }
                return _instancia;
            }
        }

        protected DatosServidor()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(string.Format("{0}\\{1}", Directory.GetCurrentDirectory(), "serverConf.xml"));
            doc.PreserveWhitespace = false;

            this.PuertoUDPClientes = int.Parse(doc.SelectSingleNode("conf/udp-port-client/text()").Value);
            this.PuertoTCPClientes = int.Parse(doc.SelectSingleNode("conf/tcp-port-client/text()").Value);
            this.FileRepository = doc.SelectSingleNode("conf/file-repository/text()").Value;
            this.PuertoUDPSincronizarServidores = int.Parse(doc.SelectSingleNode("conf/udp-port-server/text()").Value);
            this.PuertoTCPSincronizarServidores = int.Parse(doc.SelectSingleNode("conf/tcp-port-server/text()").Value);
            this.IntervaloSincronizacionServidores = int.Parse(doc.SelectSingleNode("conf/sync-server-interval/text()").Value);
            this.CantidadMaximaConexionesSincronizacion = int.Parse(doc.SelectSingleNode("conf/max-server-sync/text()").Value);

            this.IPServidor = (from addr in Dns.GetHostEntry(Dns.GetHostName()).AddressList
                               where addr.AddressFamily == AddressFamily.InterNetwork
                               select addr.ToString()).FirstOrDefault();

            this.Archivos_MD5 = new Dictionary<string, string>();
            foreach (string pathArchivo in Archivos.BuscarArchivosDirectorio(this.FileRepository))
            {
                Archivos_MD5.Add(Path.GetFileName(pathArchivo), Checksum.ObtenerChecksum(Archivos.LeerArchivo(pathArchivo)));
            }

            this.Servidores_AnchoDeBanda = new Dictionary<string, SyncAnchoDeBanda>();

            this.AnchoDeBandaServidor = new AnchoDeBandaServidor()
            {
                AnchoDeBandaTotal = double.Parse(doc.SelectSingleNode("conf/total-bandwith/text()").Value),
                AnchoDeBandaXCliente = double.Parse(doc.SelectSingleNode("conf/max-bandwith-client/text()").Value)
            };
        }

        public bool ExisteArchivo(string archivo)
        {
            return Archivos_MD5.ContainsKey(archivo);
        }

        public string ObtenerMD5(string archivo)
        {
            if (Archivos_MD5.ContainsKey(archivo))
                return Archivos_MD5[archivo];
            else
                throw new Exception(string.Format("El archivo {0} no existe", archivo));
        }

        public void AgregarArchivo(string archivo, string MD5)
        {
            if (!Archivos_MD5.ContainsKey(archivo))
                Archivos_MD5.Add(archivo, MD5);
            else
                throw new Exception(string.Format("El archivo {0} ya existe", archivo));
        }
    }
}
